/*            Copyright(c) 2006-2008 Dave Sexton           *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.ObjectModel;

namespace DaveSexton.DocProject
{
	public class StringCollectionConverter : System.ComponentModel.TypeConverter
	{
		#region Public Properties
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
		public static readonly StringCollectionConverter Default = new StringCollectionConverter();

		public bool RemoveEmptyEntries
		{
			get
			{
				return removeEmptyEntries;
			}
		}

		public ICollection<char> Separators
		{
			get
			{
				return new ReadOnlyCollection<char>(new List<char>(separators));
			}
		}
		#endregion

		#region Private / Protected
		private readonly char[] separators;
		private bool removeEmptyEntries;
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="StringCollectionConverter" /> class.
		/// </summary>
		public StringCollectionConverter()
		{
			separators = new char[] { ',' };
			removeEmptyEntries = true;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="StringCollectionConverter" /> class.
		/// </summary>
		public StringCollectionConverter(bool removeEmptyEntries)
		{
			separators = new char[] { ',' };
			this.removeEmptyEntries = removeEmptyEntries;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="StringCollectionConverter" /> class.
		/// </summary>
		public StringCollectionConverter(bool removeEmptyEntries, params char[] separators)
		{
			if (separators == null)
				throw new ArgumentNullException("separators");

			this.removeEmptyEntries = removeEmptyEntries;
			this.separators = separators;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="StringCollectionConverter" /> class.
		/// </summary>
		public StringCollectionConverter(params char[] separators)
		{
			if (separators == null)
				throw new ArgumentNullException("separators");

			this.separators = separators;
			removeEmptyEntries = true;
		}
		#endregion

		#region Methods
		public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, Type destinationType)
		{
			if (destinationType == typeof(string))
				return true;
			else
				return base.CanConvertTo(context, destinationType);
		}

		public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, Type sourceType)
		{
			if (sourceType == typeof(string))
				return true;
			else
				return base.CanConvertFrom(context, sourceType);
		}

		public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
		{
			string s = value as string;

			if (s != null)
			{
				return new Collection<string>(s.Split(separators, 
					(removeEmptyEntries) ? StringSplitOptions.RemoveEmptyEntries : StringSplitOptions.None));
			}
			else
				return base.ConvertFrom(context, culture, value);
		}

		public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
		{
			System.Collections.IEnumerable collection = value as System.Collections.IEnumerable;

			if (collection != null && destinationType == typeof(string))
			{
				StringBuilder result = new StringBuilder();

				foreach (object item in collection)
					result.AppendFormat("{0}{1}", item, separators[0]);

				if (result.Length > 0)
					// remove trailing separator
					result.Remove(result.Length - 1, 1);

				return result.ToString();
			}
			else
				return base.ConvertTo(context, culture, value, destinationType);
		}
		#endregion
	}
}
